package xyz.lne.researchgroupmanage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import xyz.lne.researchgroupmanage.entity.Research;
import xyz.lne.researchgroupmanage.entity.Task;
import xyz.lne.researchgroupmanage.entity.TaskUser;
import xyz.lne.researchgroupmanage.exception.BadRequestException;
import xyz.lne.researchgroupmanage.mapper.ResearchMapper;
import xyz.lne.researchgroupmanage.mapper.SysUserMapper;
import xyz.lne.researchgroupmanage.mapper.TaskMapper;
import xyz.lne.researchgroupmanage.mapper.TaskUserMapper;
import xyz.lne.researchgroupmanage.service.TaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import xyz.lne.researchgroupmanage.service.dataTransferObject.TaskDTO;
import xyz.lne.researchgroupmanage.service.dataTransferObject.TaskDetailDTO;
import xyz.lne.researchgroupmanage.service.dataTransferObject.TaskSimpleDTO;
import xyz.lne.researchgroupmanage.service.dataTransferObject.UserCommitTaskDTO;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author team7
 * @since 2021-01-19
 */
@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private TaskUserMapper taskUserMapper;

    @Autowired
    private ResearchMapper researchMapper;

    @Override
    @Transactional
    public TaskDetailDTO releaseTask(TaskDTO taskDTO, List<Integer> participatedUserId) {

        //检查课题id合法性
        QueryWrapper<Research> rWrapper=new QueryWrapper<>();
        rWrapper.eq("research_id",taskDTO.getResearchId());
        if(researchMapper.selectCount(rWrapper)==0){
            Map<String, Object> e = new HashMap<>();
            e.put("课题不存在", taskDTO.getResearchId());
            throw new BadRequestException(e);
        }

        //插入task表
        Task task=new Task(taskDTO);
        taskMapper.insert(task);

        //插入task_user表
        Iterator<Integer> iterator=participatedUserId.listIterator();
        while(iterator.hasNext()){
            TaskUser taskUser=new TaskUser(task.getTaskId(),iterator.next());
            taskUserMapper.insert(taskUser);
        }

        //返回taskDetailDTO
        TaskDetailDTO taskDetailDTO=new TaskDetailDTO(task);
        String userName=sysUserMapper.selectById(taskDetailDTO.getReleaseUserId()).getName();
        String researchName=researchMapper.selectById(taskDetailDTO.getResearchId()).getName();
        taskDetailDTO.setReleaseUserName(userName);
        taskDetailDTO.setResearchName(researchName);
        taskDetailDTO.setAccomplishedUsersNum(0);

        //从数据库中查询参与任务的总人数
        QueryWrapper<TaskUser> tuWrapper=new QueryWrapper<>();
        tuWrapper.eq("task_id",task.getTaskId());
        taskDetailDTO.setParticipatedUsersNum((int) taskUserMapper.selectList(tuWrapper)
                .stream().map(TaskUser::getUserId).distinct().count());

        taskDetailDTO.setUserCommitTaskDTOList(null);
        return taskDetailDTO;
    }

    @Override
    @Transactional
    public UserCommitTaskDTO commitTask(UserCommitTaskDTO userCommitTaskDTO) {

        isLegalCommit(userCommitTaskDTO.getTaskId(),userCommitTaskDTO.getCommitUserId());

        //由于不允许修改任务完成状态，为防止调用update方法时误修改状态，
        // 故将传入的信息中的任务状态位设定为“未完成”
        userCommitTaskDTO.setStatus(0);

        QueryWrapper<TaskUser> tuWrapper =new QueryWrapper<>();
        tuWrapper.eq("task_id",userCommitTaskDTO.getTaskId())
                .eq("user_id",userCommitTaskDTO.getCommitUserId())
                .eq("file_id",userCommitTaskDTO.getCommitFileId());

        TaskUser taskUser=new TaskUser(userCommitTaskDTO);

        //数据库已有任务-用户-文件三元组相同的数据行，将更新数据库
        if(taskUserMapper.selectCount(tuWrapper)>0){
            taskUserMapper.updateTaskCommit(taskUser);
        }
        else{
            taskUserMapper.insert(taskUser);
        }
        //TODO:直接返回输入值？可能存在不合理之处
        return userCommitTaskDTO;
    }

    @Override
    @Transactional
    public UserCommitTaskDTO confirmTaskStatus(UserCommitTaskDTO userCommitTaskDTO) {

        //判断当前任务中是否含有该用户
        isLegal(userCommitTaskDTO.getTaskId(),userCommitTaskDTO.getCommitUserId());

        //不允许上传文件
        userCommitTaskDTO.setCommitFileId(0);

        taskUserMapper.updateTaskStatus(new TaskUser(userCommitTaskDTO));
        //TODO:为什么要返回一个CommitTaskDTO？不明白哪里需要
        return userCommitTaskDTO;
    }

    @Override
    @Transactional
    public List<TaskSimpleDTO> getReleasedTaskListByUserId(Integer userId) {

        //查找userId对应的taskList
        QueryWrapper<Task> tWrapper=new QueryWrapper<>();
        tWrapper.eq("user_id",userId);
        List<Task> list=taskMapper.selectList(tWrapper);

        if(list.isEmpty()){
            return new ArrayList<TaskSimpleDTO>();
        }

        //将task对象批量转换为taskSimpleDTO对象
        List<TaskSimpleDTO> taskList=list
                .stream().map(this::convertToTaskSimpleDTO)
                .collect(Collectors.toList());

        return taskList;
    }

    @Override
    @Transactional
    public List<TaskSimpleDTO> getParticipatedTaskListByUserId(Integer userId) {

        //根据userId在task_user表中查找对应的行
        // 状态小于2即为“未完成”和“已完成”
        QueryWrapper<TaskUser> tuWrapper=new QueryWrapper<>();
        tuWrapper.eq("user_id",userId)
                .lt("status",2);

        List<TaskUser> taskUserList=taskUserMapper.selectList(tuWrapper);

        if(taskUserList.isEmpty()){
            return new ArrayList<TaskSimpleDTO>();
        }

        //将task_user表中的行提取出不同的taskId，并进行下一步转换
        List<Integer> taskIdList=taskUserList
                .stream().map(TaskUser::getTaskId).distinct()
                .collect(Collectors.toList());


        return taskMapper.selectBatchIds(taskIdList).stream()
                .map(this::convertToTaskSimpleDTO).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public List<TaskSimpleDTO> getAllTasksByResearchId(Integer researchId) {

        //判断课题合法性
        QueryWrapper<Research> rWrapper=new QueryWrapper<>();
        rWrapper.eq("research_id",researchId);
        if(researchMapper.selectCount(rWrapper)==0){
            Map<String, Object> e = new HashMap<>();
            e.put("课题不存在", researchId);
            throw new BadRequestException(e);
        }

        QueryWrapper<Task> tWrapper=new QueryWrapper<>();
        tWrapper.eq("research_id",researchId);

        List<Task> taskList=taskMapper.selectList(tWrapper);

        if(taskList.isEmpty()){
            //当前课题没有任务
            return new ArrayList<TaskSimpleDTO>();
        }

        List<Integer> taskIdList=taskList
                .stream().map(Task::getTaskId).distinct().collect(Collectors.toList());

        return taskMapper.selectBatchIds(taskIdList).stream()
                .map(this::convertToTaskSimpleDTO).collect(Collectors.toList());
    }

    //TODO：若该用户发布了该任务，则显示“用户没有该任务”？这种情况合理吗？
    //TODO:mapper方法的返回值为空列表而非null，需要调整代码实现逻辑
    //TODO:更新后应该将数据重新查询出来返回，而非直接返回输入值
    @Override
    @Transactional
    public TaskDetailDTO getTaskUserDetailByTaskId(Integer taskId, Integer userId) {

        isLegal(taskId,userId);

        TaskDetailDTO taskDetailDTO =getCommonDetailDTOByTaskId(taskId);

        QueryWrapper<TaskUser> tuWrapper =new QueryWrapper<>();
        tuWrapper.eq("task_id",taskId).eq("user_id",userId);

        List<UserCommitTaskDTO> commitTaskDTOList=taskUserMapper.selectList(tuWrapper)
                .stream().map(this::convertToUserCommitTaskDTO).collect(Collectors.toList());


        taskDetailDTO.setUserCommitTaskDTOList(commitTaskDTOList);

        return taskDetailDTO;
    }


    @Override
    @Transactional
    public TaskDetailDTO getTaskAdminDetailByTaskId(Integer taskId) {

        TaskDetailDTO taskDetailDTO =getCommonDetailDTOByTaskId(taskId);

        QueryWrapper<TaskUser> tuWrapper =new QueryWrapper<>();
        tuWrapper.eq("task_id",taskId);


        List<UserCommitTaskDTO> commitTaskDTOList=taskUserMapper.selectList(tuWrapper)
                .stream().map(this::convertToUserCommitTaskDTO).collect(Collectors.toList());

        taskDetailDTO.setUserCommitTaskDTOList(commitTaskDTOList);

        return taskDetailDTO;

    }

    @Override
    @Transactional
    public Boolean deleteTaskByResearchId(Integer researchId){

        //判断课题合法性
       QueryWrapper<Research> rWrapper=new QueryWrapper<>();
       rWrapper.eq("research_id",researchId);
        if (researchMapper.selectCount(rWrapper)==0) {
            Map<String, Object> e = new HashMap<>();
            e.put("删除的课题组不存在", researchId);
            throw new BadRequestException(e);
        }

        QueryWrapper<Task> taskQueryWrapper = new QueryWrapper<>();
        taskQueryWrapper.eq("research_id", researchId);

        taskMapper.delete(taskQueryWrapper);

        return true;
    }

    @Override
    public List<TaskSimpleDTO> getUserTaskListInResearch(Integer userId, Integer researchId) {
        QueryWrapper<TaskUser> tKWrapper=new QueryWrapper<>();
        tKWrapper.eq("user_id",userId);
        if(taskUserMapper.selectCount(tKWrapper)==0){
            //当前用户没有参与任何任务
            return new ArrayList<>();
        }
        else {
            //拿到当前用户参与的任务IdList
            List<Integer> taskIdList=taskUserMapper.selectList(tKWrapper)
                    .stream().map(TaskUser::getTaskId).distinct()
                    .collect(Collectors.toList());

            //判断当前用户参与的任务IdList是否是当前课题，是则保留，否则删去
           List<Integer> ansIdList=taskIdList.stream().filter(i->isPublisher(i, researchId))
                   .collect(Collectors.toList());

           if(!ansIdList.isEmpty()){
               return taskMapper.selectBatchIds(ansIdList).stream()
                       .map(this::convertToTaskSimpleDTO).collect(Collectors.toList());
           }
            else {
               return new ArrayList<>();
           }
        }
    }

    @Override
    public Integer getUserTaskStatus(Integer userId, Integer taskId) {

        QueryWrapper<TaskUser> tUWrapper=new QueryWrapper<>();
        tUWrapper.eq("user_id",userId)
                .eq("task_id",taskId)
                .eq("file_id",0);
        if(taskUserMapper.selectCount(tUWrapper)==0){
            Map<String, Object> e = new HashMap<>();
            e.put("该用户没有加入该任务", taskId);
            throw new BadRequestException(e);
        }
        else{
            return taskUserMapper.selectOne(tUWrapper).getStatus();
        }

    }

    @Override
    public void isLegal(Integer taskId) {
        QueryWrapper<Task> wrapper=new QueryWrapper<>();
        wrapper.eq("task_id",taskId);

        if(taskMapper.selectCount(wrapper)==0){
            Map<String, Object> e = new HashMap<>();
            e.put("请求中包含不存在的任务", taskId);
            throw new BadRequestException(e);
        }
    }

    @Override
    public void isLegal(Integer taskId, Integer userId) {
        isLegal(taskId);
        QueryWrapper<TaskUser> taskUserQueryWrapper=new QueryWrapper<>();
        taskUserQueryWrapper.eq("task_id",taskId)
                            .eq("user_id",userId);
        if(taskUserMapper.selectCount(taskUserQueryWrapper)!=0){
            taskUserQueryWrapper.eq("status",2);
            if(taskUserMapper.selectCount(taskUserQueryWrapper)>0){
                Map<String, Object> e = new HashMap<>();
                e.put("请求中包含不存在或已拒绝的任务:", taskId);
                throw new BadRequestException(e);
            }
            else {
                return;
            }
        }
        else {
            Map<String, Object> e = new HashMap<>();
            e.put("该用户没有该任务", taskId);
            throw new BadRequestException(e);
        }

    }


    @Override
    public void isLegalCommit(Integer taskId, Integer userId) {
        QueryWrapper<TaskUser> wrapper=new QueryWrapper<>();
        wrapper.eq("user_id",userId)
                .eq("task_id",taskId)
                .eq("file_id",0);
        if(taskUserMapper.selectCount(wrapper)==1){
            if(taskUserMapper.selectOne(wrapper).getStatus()==0){
                //当且仅当用户接受任务，并且处于未完成状态时可以提交任务。
                return ;
            }
        }
        else {
            Map<String, Object> e = new HashMap<>();
            e.put("当且仅当用户接受任务，并且处于未完成状态时可以提交任务。",null);
            throw new BadRequestException(e);
        }
    }

    @Override
    public Boolean isAdminInTask(Integer taskId, Integer userId) {
        QueryWrapper<Task> tWrapper=new QueryWrapper<>();
        tWrapper.eq("task_id",taskId).eq("user_id",userId);

        return taskMapper.selectCount(tWrapper) == 1;
    }


    private TaskDetailDTO getCommonDetailDTOByTaskId(Integer taskId){

        TaskDetailDTO taskDetailDTO=new TaskDetailDTO(taskMapper.selectById(taskId));

        String userName=sysUserMapper.selectById(taskDetailDTO.getReleaseUserId()).getName();
        String researchName=researchMapper.selectById(taskDetailDTO.getResearchId()).getName();

        taskDetailDTO.setReleaseUserName(userName);
        taskDetailDTO.setResearchName(researchName);
        taskDetailDTO.setParticipatedUsersNum(getTotalPeopleNum(taskId));
        taskDetailDTO.setAccomplishedUsersNum(getFinishPeopleNum(taskId));
        taskDetailDTO.setUserCommitTaskDTOList(null);

        return taskDetailDTO;
    }

    private TaskSimpleDTO convertToTaskSimpleDTO(Task task){

        TaskSimpleDTO dto=new TaskSimpleDTO();
        dto.setTaskId(task.getTaskId());
        dto.setName(task.getName());
        dto.setResearchName(researchMapper.selectById(task.getResearchId()).getName());
        dto.setCreateTime(task.getCreateTime());

        dto.setTotalPeopleNum(getTotalPeopleNum(task.getTaskId()));
        dto.setFinishPeopleNum(getFinishPeopleNum(task.getTaskId()));

        return dto;
    }

    private Integer getFinishPeopleNum(Integer taskId){

        QueryWrapper<TaskUser> tuWrapper=new QueryWrapper<>();
        tuWrapper.eq("task_id",taskId);

        List<TaskUser> taskUserList=taskUserMapper.selectList(tuWrapper);

        return (int)taskUserList.stream().filter(t->t.getStatus()==1)
                .map(TaskUser::getUserId).distinct().count();

    }

    private Integer getTotalPeopleNum(Integer taskId){

        QueryWrapper<TaskUser> tuWrapper=new QueryWrapper<>();
        tuWrapper.eq("task_id",taskId);

        List<TaskUser> taskUserList=taskUserMapper.selectList(tuWrapper);

        return (int)taskUserList.stream().filter(t->t.getStatus()<2)
                .map(TaskUser::getUserId).distinct().count();
    }

    /**
     * 判断当前任务是否属于该课题
     * @param taskId
     * @param researchId
     * @return
     */
    public Boolean isPublisher(Integer taskId,Integer researchId){
        QueryWrapper<Task> wrapper=new QueryWrapper<>();
        wrapper.eq("task_id",taskId).eq("research_id",researchId);

        return taskMapper.selectCount(wrapper)!=0;
    }

    private UserCommitTaskDTO convertToUserCommitTaskDTO(TaskUser taskUser){

        UserCommitTaskDTO dto=new UserCommitTaskDTO();

        dto.setTaskId(taskUser.getTaskId());
        dto.setCommitUserId(taskUser.getUserId());
        dto.setCommitContent(taskUser.getContent());
        dto.setCommitFileId(taskUser.getFileId());
        dto.setCommitTime(taskUser.getCommitTime());
        dto.setRemark(taskUser.getRemark());
        dto.setStatus(taskUser.getStatus());

        return dto;
    }



}
